import os
import logging
import inspect
import sys
from time import strftime

from utils.path_manager import path_manager
from utils.emoji_utils import EmojiUtils


class Log:
    def __init__(self):
        self.__now = strftime("%Y-%m-%d-%H")
        self.__log_name = os.path.join(path_manager.log_path, '{0}.log'.format(self.__now))

        # 创建一个logger
        self.__logger = logging.getLogger()

        # 避免重复添加handler
        if not self.__logger.handlers:
            self.__logger.setLevel(logging.DEBUG)
            
            # 检查是否在pytest环境中运行
            is_pytest = self._is_pytest_running()
            
            # 在pytest环境下，设置propagate=True让pytest捕获日志
            # 在非pytest环境下，设置propagate=False防止重复输出
            self.__logger.propagate = is_pytest

            # 创建一个handler，用于写入日志文件
            fh = logging.FileHandler(self.__log_name, 'a', encoding='utf-8')
            fh.setLevel(logging.INFO)
            
            # 定义handler的输出格式
            formatter = logging.Formatter(fmt=self.fmt)
            fh.setFormatter(formatter)

            # 给logger添加文件handler
            self.__logger.addHandler(fh)
            
            # 只有在非pytest环境下才添加控制台handler
            if not is_pytest:
                sh = logging.StreamHandler()
                sh.setLevel(logging.INFO)
                sh.setFormatter(formatter)
                self.__logger.addHandler(sh)

    @property
    def fmt(self):
        return '%(asctime)s [%(levelname)s] %(message)s'

    def _log_with_caller_info(self, level, message, emoji):
        """记录日志并包含调用者信息"""
        # 获取调用栈信息
        frame = inspect.currentframe()
        try:
            # 跳过当前方法和调用的日志方法，获取真正的调用者
            caller_frame = frame.f_back.f_back
            filename = caller_frame.f_code.co_filename
            function_name = caller_frame.f_code.co_name
            line_number = caller_frame.f_lineno

            # 格式化调用者信息
            caller_info = f"[{os.path.basename(filename)}:{function_name}:{line_number}]"
            formatted_message = f"{caller_info} {emoji} {message}"

            # 记录日志
            getattr(self.__logger, level)(formatted_message)
        finally:
            del frame

    def info(self, message):
        self._log_with_caller_info('info', message, EmojiUtils.INFO)

    def error(self, message):
        self._log_with_caller_info('error', message, EmojiUtils.ERROR)

    def warning(self, message):
        self._log_with_caller_info('warning', message, EmojiUtils.WARNING)

    def debug(self, message):
        self._log_with_caller_info('debug', message, EmojiUtils.DEBUG)

    def success(self, message):
        self._log_with_caller_info('info', message, EmojiUtils.SUCCESS)

    def test_step(self, step_name, description=None):
        step_info = f"步骤: {step_name}"
        if description:
            step_info += f" - {description}"
        self._log_with_caller_info('info', step_info, EmojiUtils.TEST_STEP)
        
    def _is_pytest_running(self):
        """检查是否在pytest环境中运行"""
        # 方法1：检查sys.modules中是否有pytest
        if 'pytest' in sys.modules:
            return True
        # 方法2：检查环境变量
        if os.environ.get('PYTEST_CURRENT_TEST') is not None:
            return True
        return False
